// $Id: loggercountinsert.cpp 65 2004-10-27 21:44:50Z hansemil $
#include "loggercountinsert.h"
#include "loghandler.h"
#include "node.h"
#include "keydistancehelper.h"
#include <iostream>
#include <list>
#include <vector>
using namespace std;

/**
 * Init members and register apropriate listeners at the log handler.
 */
LoggerCountInsert::LoggerCountInsert()
	: 	m_sizeListSum(0), m_failedCount(0), m_collisionCount(0)
{
	LogHandler::getInstance()->addLogger(this, "clock_tick");
	LogHandler::getInstance()->addLogger(this, "node_routeFile");
}

/**
 * Opens file for writing and stores the Eos pointer
 */
void LoggerCountInsert::eos_simulate_start(void *eos)
{
	openFile(&m_fout, "countinsert.csv");
	m_fout << "Time Step, Average, Minimum, First Quartile, Median, Third Quartile, Maximum, Successful Request Count, Failed Request Count, Collided Request Count" << endl;

	m_eos = (Eos *)eos;
}

/**
 * Closes file
 */
void LoggerCountInsert::eos_simulate_stop(void *eos)
{
	m_fout.close();
}

/**
 * Writes the statistics for each tick
 */
void LoggerCountInsert::clock_tick(unsigned int time)
{

	// Write time step
	m_fout << time;

	// Write statistics
	writeCountStats(m_fout, m_sizeList, m_sizeListSum);
	m_fout << "," << m_failedCount;
	m_fout << "," << m_collisionCount;

	// Write end
	m_fout << endl;

	// Clear variables for next timestep
	m_sizeList.clear();
	m_failedCount = 0;
	m_collisionCount = 0;
	m_sizeListSum = 0;
}

/**
 * Checks if a insert call is a final success or final fail and saves it for writing on tick
 */
void LoggerCountInsert::node_routeFile(void *thisNode, void *requestor, void *params_in, unsigned char result)
{
	m_params = (NodeRequestFileParameters *)params_in;
	// Check that it's an insert
	if(m_params->m_insert){

		// Final success, find nodes "closer" to the inserted file than the chosen one
		if(result && m_params->m_insertComplete && thisNode == requestor){
			int closerNodesCount = 0;

			/// @todo Rework the insert logger to logg more interesting stuff
			// This won't work really. Hard to know what would have been a better node...
			/*
			// Build list of compared ids and sort it
			std::list<Node *> *nodes = m_eos->getNodes();
			list<KeyDistanceHelper> neighborDistance;
			for (list<Node *>::iterator node=nodes->begin(); node!=nodes->end(); node++) {
				// Calc freenet style distance
				int distance = abs((int) ((*node)->getId() - m_params->m_file->m_hash));
				neighborDistance.push_back(KeyDistanceHelper(distance, *node));
			}
			neighborDistance.sort(SortKeyDistanceHelper());

			// Find how many closer nodes there are
			for (list<KeyDistanceHelper>::iterator node=neighborDistance.begin(); node!=neighborDistance.end() && !(*(*node).m_node).getStoredFile(m_params->m_file); node++) {
				closerNodesCount++;
			}
			*/

			// Save better nodes count
			m_sizeListSum += closerNodesCount;
			m_sizeList.push_back(closerNodesCount);
		}
		// Final collision
		else if(!result && thisNode == requestor){
			m_collisionCount++;
		}
		// Final fail
		else if(result && !m_params->m_insertComplete && thisNode == requestor){
			m_failedCount++;
		}
	}
}
